package com.caiden_micheal.dynamic.form.service.impl;

import com.alibaba.fastjson2.JSON;
import com.caiden_micheal.base.constant.LoggerHead;
import com.caiden_micheal.base.domain.AjxResult;
import com.caiden_micheal.base.domain.workflow.ProcessEdge;
import com.caiden_micheal.base.domain.workflow.ProcessNode;
import com.caiden_micheal.base.dto.PageDTO;
import com.caiden_micheal.base.utils.BaseContext;
import com.caiden_micheal.base.utils.JsonValidator;
import com.caiden_micheal.dynamic.workflow.utils.EdgeParsingTool;
import com.caiden_micheal.dynamic.workflow.utils.NodeParsingTool;
import com.caiden_micheal.base.vo.PageVo;
import com.caiden_micheal.dynamic.form.domain.DynamicForm;
import com.caiden_micheal.dynamic.form.dto.*;
import com.caiden_micheal.dynamic.form.mapper.DFormMapper;
import com.caiden_micheal.dynamic.form.service.DFormService;
import com.caiden_micheal.dynamic.form.vo.DFormWithDataVO;
import com.caiden_micheal.dynamic.form.vo.FormSelectDataVO;
import com.caiden_micheal.dynamic.form_workflow.domain.FormWorkflow;
import com.caiden_micheal.dynamic.form_workflow.mapper.FormWorkflowMapper;
import com.caiden_micheal.dynamic.process.domain.DynamicProcess;
import com.caiden_micheal.dynamic.process.mapper.DProcessMapper;
import com.caiden_micheal.dynamic.record.domain.DProcessRecord;
import com.caiden_micheal.dynamic.record.mapper.DProcessRecordMapper;
import com.caiden_micheal.dynamic.workflow.domain.DynamicWorkflow;
import com.caiden_micheal.dynamic.workflow.mapper.DWorkflowMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.List;
import java.util.Objects;

@Service
public class DFormServiceImpl implements DFormService {
    private static final Logger logger = LoggerFactory.getLogger(DFormServiceImpl.class);

    @Autowired
    private DFormMapper dFormMapper;
    @Autowired
    private FormWorkflowMapper formWorkflowMapper;
    @Autowired
    private DProcessMapper dProcessMapper;
    @Autowired
    private DWorkflowMapper dWorkflowMapper;
    @Autowired
    private DProcessRecordMapper dProcessRecordMapper;

    @Transactional
    @Override
    public AjxResult addDForm(AddDFormDTO addDFormDTO) {
        if (addDFormDTO == null || addDFormDTO.getWidgetList() == null || addDFormDTO.getFormConfig() == null) {
            logger.warn("参数传入有误, dynamicFormDTO: " + addDFormDTO);
            return AjxResult.paramError("参数传递有误");
        }
        if (!(JsonValidator.validJSON(addDFormDTO.getWidgetList()) &&
                JsonValidator.validJSON(addDFormDTO.getFormConfig()))) {
            return AjxResult.paramError("参数传递有误，非JSON字符串");
        }
        try {
            if (addDFormDTO.getId() == null) {
                if (addDFormDTO.getDisplayName() == null) {
                    return AjxResult.paramError("参数传递有误");
                } else {
                    DynamicForm dynamicForm = dFormMapper.findByDisplayName(addDFormDTO.getDisplayName());
                    if (dynamicForm != null) {
                        return AjxResult.paramError("表单名称已存在，请更换后重试");
                    }
                    dynamicForm = new DynamicForm();
                    BeanUtils.copyProperties(addDFormDTO, dynamicForm);
                    dynamicForm.setCreatorId(Long.valueOf(BaseContext.getInfo().get("userId").toString()));
                    dynamicForm.setCreatorUsername(String.valueOf(BaseContext.getInfo().get("username")));
                    dFormMapper.insertForm(dynamicForm);
                    return AjxResult.success(dynamicForm.getId());
                }
            } else {
                DynamicForm dynamicForm = dFormMapper.findById(addDFormDTO.getId());
                if (dynamicForm == null) {
                    return AjxResult.paramError("修改的表单不存在");
                } else {
                    List<FormWorkflow> formWorkflowByFormId = formWorkflowMapper.findFormWorkflowByFormId(addDFormDTO.getId());
                    if (formWorkflowByFormId != null && formWorkflowByFormId.size() != 0) {
                        return AjxResult.paramError("该表单模板已被" + formWorkflowByFormId.size() + "个逻辑流程模板引用，无法直接操作");
                    }
                }
                if (!Objects.equals(addDFormDTO.getDisplayName(), dynamicForm.getDisplayName())) {
                    DynamicForm tempDFormMapper = dFormMapper.findByDisplayName(addDFormDTO.getDisplayName());
                    if (tempDFormMapper != null) {
                        return AjxResult.paramError("逻辑工作流模板名称已存在");
                    } else {
                        dynamicForm.setDisplayName(addDFormDTO.getDisplayName());
                    }
                }
                dynamicForm.setFormConfig(addDFormDTO.getFormConfig());
                dynamicForm.setWidgetList(addDFormDTO.getWidgetList());
                dFormMapper.updateForm(dynamicForm);
                return AjxResult.success(dynamicForm.getId());
            }
        } catch (Exception e) {
            logger.error(e.toString());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjxResult.unknownError("数据库操作异常");
        }
    }

    @Override
    public PageDTO findDFormByCondition(FindDFormPageQueryDTO findDFormPageQueryDTO) {
        PageVo page = findDFormPageQueryDTO.getPage();
        if (page == null) {
            logger.warn(LoggerHead.warnHead() + "findDFormPageQueryDTO.page is Null!");
            return null;
        }
        page.setCurrentIndex((long) (page.getCurrentPage() - 1) * page.getPageSize());
        List<DynamicForm> dformList = dFormMapper.findFormPageQueryCondition(findDFormPageQueryDTO);
        page.setCount(dFormMapper.findFormPageQueryConditionCount(findDFormPageQueryDTO));
        return new PageDTO(dformList, page);
    }

    @Override
    public AjxResult findDFormOne(FindDFormOneDTO findDFormOneDTO) {
        if (findDFormOneDTO == null || !(findDFormOneDTO.getId() != null || findDFormOneDTO.getProcessId() != null)) {
            return AjxResult.paramError("参数传递有误");
        }
        Long formId, workflowId = null;
        DynamicProcess dynamicProcess = null;
        try {
            if (findDFormOneDTO.getProcessId() != null) {
                dynamicProcess = dProcessMapper.findById(findDFormOneDTO.getProcessId());
                if (dynamicProcess == null) {
                    logger.warn("DProcess does not exist, processId: " + findDFormOneDTO.getProcessId());
                    return AjxResult.paramError("流程不存在");
                }
                FormWorkflow formWorkflow = formWorkflowMapper.findById(dynamicProcess.getFormWorkflowId());
                if (formWorkflow != null) {
                    formId = formWorkflow.getFormId();
                    workflowId = formWorkflow.getWorkflowId();
                } else {
                    logger.warn("The logical workflow template does not exist, formWorkflowId: " + dynamicProcess.getFormWorkflowId());
                    return AjxResult.paramError("逻辑工作流模板不存在");
                }
            } else {
                formId = findDFormOneDTO.getId();
            }
            DynamicForm dynamicForm = dFormMapper.findById(formId);
            if (dynamicForm == null) {
                return AjxResult.paramError("表单不存在");
            }
            if (findDFormOneDTO.getPermissionFlag() == null || findDFormOneDTO.getPermissionFlag()) {
                if (!Objects.equals(dynamicForm.getCreatorId(), Long.valueOf(BaseContext.getInfo().get("userId").toString()))) {
                    return AjxResult.paramError("表单不存在");
                }
            }
            if (dynamicProcess != null) {
                DynamicWorkflow dynamicWorkflow = dWorkflowMapper.findById(workflowId);
                if (dynamicWorkflow == null) {
                    return AjxResult.paramError("工作流不存在");
                }
                List<DProcessRecord> dProcessRecordList = dProcessRecordMapper.findByProcessIdHasPerson(dynamicProcess.getId());
                if (dProcessRecordList == null) {
                    return AjxResult.paramError("流程处理为空");
                }
                List<ProcessNode> processNodeList = NodeParsingTool.parseNodeList(dynamicWorkflow.getNodes());
                if (processNodeList == null || processNodeList.size() == 0) {
                    return AjxResult.paramError("节点数据集转换异常");
                }
                List<ProcessEdge> processEdgeList = EdgeParsingTool.parseEdgeList(dynamicWorkflow.getEdges());
                if (processEdgeList == null || processEdgeList.size() == 0) {
                    return AjxResult.paramError("边数据集转换异常");
                }
                NodeParsingTool.processNode(dProcessRecordList, processNodeList, processEdgeList);
                DFormWithDataVO dFormWithDataVO = new DFormWithDataVO();
                BeanUtils.copyProperties(dynamicForm, dFormWithDataVO);
                dFormWithDataVO.setFormData(dynamicProcess.getFormData());
                dFormWithDataVO.setEdges(JSON.toJSONString(processEdgeList));
                dFormWithDataVO.setNodes(JSON.toJSONString(processNodeList));
                return AjxResult.success(dFormWithDataVO);
            } else {
                return AjxResult.success(dynamicForm);
            }
        } catch (Exception e) {
            logger.error(e.toString());
            return AjxResult.unknownError("数据库操作异常");
        }
    }

    @Transactional
    @Override
    public AjxResult findFormSelectData(FindFormSelectDataDTO findFormSelectDataDTO) {
        if (findFormSelectDataDTO == null || findFormSelectDataDTO.getDisplayName() == null) {
            return AjxResult.paramError("参数传递有误");
        }
        try {
            List<FormSelectDataVO> formSelectDatumVOS = dFormMapper.findFormSelectData(findFormSelectDataDTO.getDisplayName());
            return AjxResult.success(formSelectDatumVOS);
        } catch (Exception e) {
            logger.error(e.toString());
            return AjxResult.unknownError("数据库操作异常");
        }
    }

    @Transactional
    @Override
    public AjxResult removeDForm(RemoveDFormDTO removeDFormDTO) {
        if (removeDFormDTO == null || removeDFormDTO.getId() == null) {
            return AjxResult.paramError("参数传递有误");
        }
        List<FormWorkflow> formWorkflowByFormId = formWorkflowMapper.findFormWorkflowByFormId(removeDFormDTO.getId());
        if (formWorkflowByFormId != null && formWorkflowByFormId.size() != 0) {
            return AjxResult.paramError("该表单模板已被" + formWorkflowByFormId.size() + "个逻辑流程模板引用，无法直接操作");
        }
        try {
            dFormMapper.removeDForm(removeDFormDTO.getId());
            return AjxResult.success("删除成功");
        } catch (Exception e) {
            logger.error(e.toString());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjxResult.unknownError("数据库操作异常");
        }
    }
}
